Skip to content

fix(native-grants): fail loudly when native OTP/register hit a realm with grants disabled#102

Merged
windischb merged 1 commit into
developfrom
fix/native-grants-disabled-loud-error
Jun 23, 2026
Merged

fix(native-grants): fail loudly when native OTP/register hit a realm with grants disabled#102
windischb merged 1 commit into
developfrom
fix/native-grants-disabled-loud-error

Conversation

@windischb

Copy link
Copy Markdown
Contributor

The problem (real onboarding trap)

Entering an email and clicking login on a realm whose Native Passwordless Grants flag is off produced no email and no error. The OTP-request endpoint returned a silent uniform 200 ("If your email is registered…") and dispatched nothing — indistinguishable from "code sent", and impossible to diagnose unless you already knew the realm toggle existed. (Hit during AmZettel onboarding.)

Why it's safe to surface

Whether native grants are enabled is a realm/App configuration state, not a per-email signal — so an explicit error leaks nothing the anti-enumeration branch must protect. The native passkey-begin endpoint and the /connect/token grant already reject loudly when the flag is off; the OTP-request and native-register endpoints were the silent outliers. This aligns them.

Changes

Backend

  • NativeOtpEndpoints — realm-grants-off → 400 NativeGrants.Disabled + a WARN log (lands in the per-realm error feed) instead of a silent 200. The email-existence branch below is untouched → anti-enumeration preserved.
  • NativeRegisterEndpoints — split the realm-grants check out of the combined eligible flag: grants-off is now a loud 400; the posture gate stays a uniform no-op (a per-App routing choice, not a misconfiguration).

Frontend

  • ClientDetails — warn when a client carries a native grant but the realm flag is off (the inverse of the existing "enabled" info note). Catches the misconfiguration at setup time, before the first login attempt. + German i18n.

Tests

  • OTP-request realm-off now asserts 400 + NativeGrants.Disabled + no send.
  • New native-register realm-off coverage.
  • Rate-limit test asserts under-limit requests are not throttled (flag-independent).
  • Full affected native set: 29/29 green.

Docsnative-apps.md Flow 1 note + errors-table row.

Defense-in-depth

Two complementary catches now make the silent failure nearly impossible: the frontend warning catches the admin at config time, and the backend error catches the consumer at the first login attempt.

🤖 Generated with Claude Code

…with grants disabled

Entering an email and clicking login on a realm whose Native Passwordless
Grants flag is off produced NO email and NO error — the OTP-request endpoint
returned a silent uniform 200 ("If your email is registered…") and dispatched
nothing. Indistinguishable from "code sent", impossible to diagnose without
already knowing the realm toggle exists.

Whether native grants are enabled is a realm/App configuration state, not a
per-email signal, so surfacing it leaks nothing the anti-enumeration branch
must protect. The native passkey-begin endpoint and the /connect/token grant
already reject loudly when the flag is off; the OTP-request and native-register
endpoints were the silent outliers. Align them.

Backend:
- NativeOtpEndpoints: realm-grants-off → 400 NativeGrants.Disabled + WARN log
  (lands in the per-realm error feed) instead of a silent 200. The
  email-existence branch below is untouched, so anti-enumeration is preserved.
- NativeRegisterEndpoints: split the realm-grants check out of the combined
  eligible flag — grants-off is now a loud 400; the posture gate stays a
  uniform no-op (a per-App routing choice, not a misconfiguration).

Frontend:
- ClientDetails: warn when a client carries a native grant but the realm flag
  is OFF (the inverse of the existing "enabled" info note) — catches the
  misconfiguration at setup time, before the first login attempt.

Tests:
- NativeOtpRequest realm-off now asserts 400 + NativeGrants.Disabled + no send.
- New NativeRegister realm-off coverage.
- Rate-limit test asserts under-limit requests are NOT throttled (flag-independent).

Docs: native-apps.md Flow 1 note + errors-table row.

Surfaced by the AmZettel onboarding (Atlas: requests-amzettel-bff-single-credential).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@windischb windischb merged commit 40c642e into develop Jun 23, 2026
8 checks passed
@windischb windischb deleted the fix/native-grants-disabled-loud-error branch June 23, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant